home *** CD-ROM | disk | FTP | other *** search
- #import "Modem.h"
- #import <stdio.h>
- #import <libc.h>
- /* int usleep(unsigned int); */
- /* Call 'capture' instead of 'write' to perform filtering.
- For now, we replace cr/lf with lf */
-
- void capture(int fd, char *buf, int size)
- {
- static int lastchar=0;
-
- while (size>0) {
- if (*buf!='\r')
- write(fd,buf,1);
- if (lastchar=='\r' && *buf!='\n') {
- write(fd,&lastchar,1);
- write(fd,buf,1);
- }
- lastchar = *(buf++);
- size--;
- }
- }
-
- /* need to catch interrupt if user wished to kill
- child process */
- void handler(int sig)
- {
- return;
- }
-
- @implementation Modem
-
- + newPort:(char *)dev speed:(int)bps
- {
- self = [super newReadWriteDevice:dev];
- if (self==nil)
- return self;
- capturefd = (-1);
- sendProt = xmodem1k;
- receiveProt = zmodem;
- [[[[self setRaw] setParity:NOPARITY] unSetCrmod] unSetEcho];
- [self setSpeed:bps];
- return self;
- }
-
- + newA
- {
- return [self newPort:'a' speed:2400];
- }
-
- + newB
- {
- return [self newPort:'b' speed:2400];
- }
-
- - hangup // by clearing Data Terminal Ready signal to modem
- {
- char buf[200];
- /* the following apparently doesn't work */
- printf("\nAttempting to hang up phone via DTR\n");
- ioctl(fd,TIOCCDTR,0);
- sleep(1);
- ioctl(fd,TIOCSDTR,0);
- printf("\nAttempting to hang up phone\n");
- [self readInto:buf]; // flush modems buffer
- [self writeOut:"+++"];
- sleep(4);
- if ([self readInto:buf] && strncmp(buf,"OK",2)) {
- [self writeOut:"ATH\r"];
- printf("success\n");
- }
- return self;
- }
-
- - forkExecArgv:(char **)argv
- {
- int pid;
- void (*oldhandler)(int);
-
- pid = fork();
- if (pid!=0) {
- oldhandler = signal(SIGINT, handler);
- wait(0);
- fprintf(stderr,"\r\nFile transfer process ended\r\n");
- signal(SIGINT, oldhandler);
- return self;
- }
- /* the child runs with stdin and stdout redirected to modem */
- dup2(fd,0);
- dup2(fd,1);
- execv(argv[0],argv);
- return self; // this line is never reached
- }
-
- - receiveZmodem
- {
- char *argv[]={"/usr/local/bin/rz",NULL};
- return [self forkExecArgv:argv];
- }
-
- - sendZmodemFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/sz";
- argv[1]=filename;
- argv[2]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - receiveYmodem
- {
- char *argv[]={"/usr/local/bin/rb",NULL};
- return [self forkExecArgv:argv];
- }
-
- - sendYmodemFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/sb";
- argv[1]=filename;
- argv[2]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - receiveXmodemFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/rx";
- argv[1]=filename;
- argv[2]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - sendXmodemFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/sx";
- argv[1]=filename;
- argv[2]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - receiveXmodem1kFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/rx";
- argv[1]="-k";
- argv[2]=filename;
- argv[3]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - sendXmodem1kFile:(char *)filename
- {
- char *argv[10];
- argv[0]="/usr/local/bin/sx";
- argv[1]="-k";
- argv[2]=filename;
- argv[3]=NULL;
- return [self forkExecArgv:argv];
- }
-
- - receive
- {
- char file[200];
-
- switch (receiveProt) {
- case xmodem:
- printf("\nEnter file in which to receive:");
- scanf("%s",file);
- [self receiveXmodemFile:file];
- break;
- case xmodem1k:
- printf("\nEnter file in which to receive:");
- scanf("%s",file);
- [self receiveXmodem1kFile:file];
- break;
- case ymodem:
- [self receiveYmodem];
- break;
- case zmodem:
- [self receiveZmodem];
- break;
- default:
- fprintf(stderr,"\nIllegal protocol\n\n");
- break;
- }
- return self;
- }
-
- - sendFile:(char *)filename
- {
- switch (sendProt) {
- case xmodem:
- [self sendXmodemFile:filename];
- break;
- case xmodem1k:
- [self sendXmodem1kFile:filename];
- break;
- case ymodem:
- [self sendYmodemFile:filename];
- break;
- case zmodem:
- [self sendZmodemFile:filename];
- break;
- default:
- fprintf(stderr,"\nIllegal protocol\n\n");
- break;
- }
- return self;
- }
-
- - setProtocol:(char)p dir:(enum direction)dir
- {
- enum protocol *prot;
- prot = (dir==tohost)? &sendProt: &receiveProt;
- switch (p) {
- case 'x':
- case 'X':
- *prot = xmodem;
- break;
- case '1':
- *prot = xmodem1k;
- break;
- case 'y':
- case 'Y':
- *prot = ymodem;
- break;
- case 'z':
- case 'Z':
- *prot = zmodem;
- break;
- default:
- fprintf(stderr,"\nIllegal protocol, specify x,y,or z\n\n");
- break;
- }
- return self;
- }
-
- - (int) getProtocolDir:(enum direction)dir
- {
- enum protocol prot;
- prot = (dir==tohost)? sendProt: receiveProt;
- switch (prot) {
- case xmodem:
- return 'x';
- break;
- case xmodem1k:
- return '1';
- break;
- case ymodem:
- return 'y';
- break;
- case zmodem:
- return 'z';
- break;
- default:
- fprintf(stderr,"\nProtocol Undefined value = %d\n\n",prot);
- break;
- }
- return 0;
- }
-
- - captureSessionInFile:(char *)filename
- {
- capturefd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0644);
- return self;
- }
-
- - endCapture
- {
- close(capturefd);
- capturefd = (-1);
- return self;
- }
-
- - (BOOL) isCapturing
- {
- return (capturefd >= 0);
- }
-
- - (int) readInto:(char *)buf //returns number of characters read into buf
- {
- int chars;
- chars = [super readInto:buf];
- if (capturefd >= 0) capture(capturefd, buf, chars);
- return chars;
- }
-
- /* When sending several character strings to a modem,
- * sometimes need to limit the rate. This simulates
- * typing by hand.
- * The delay is in microseconds, and is only a lower
- * limit. Because of the overhead of calling usleep(),
- * the pacing is noticeable even when delay = 1 uSec,
- * so I imagine a value of 1 will usually suffice.
- */
- - (int) writeOut:(char *)buf paced:(unsigned long)delay
- {
- int len = strlen(buf);
- char onechar[2];
- onechar[1]=0;
- while (len-- > 0) {
- onechar[0]=*buf++;
- if ([self writeOut:onechar] < 0)
- return -1;
- usleep(delay);
- }
- return len;
- }
-
- @end
-